package com.atguigu.paymentdemo.config;

import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import org.springframework.stereotype.Component;


import javax.annotation.PostConstruct;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;

@Slf4j
@Component
@PropertySource("classpath:wxpay.properties") //读取配置文件
@ConfigurationProperties(prefix="wxpay") //读取wxpay节点
@Data //使用set方法将wxpay节点中的值填充到当前类的属性中
public class WxPayConfig {

    // 商户号
    private String mchId;

    // 商户API证书序列号
    private String mchSerialNo;

    // 商户私钥文件
    private String privateKeyPath;

    // APIv3密钥
    private String apiV3Key;

    // APPID
    private String appid;

    // 微信服务器地址
    private String domain;

    // 接收结果通知地址
    private String notifyDomain;
    public WxPayConfig(){
        System.out.println();
    }



    public PrivateKey getPrivateKey(){
        try{
            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
                    new FileInputStream(privateKeyPath));
            return merchantPrivateKey;

        }catch (Exception e){
            throw new RuntimeException("文件不存在");
        }

    }

    /**
     * 完成签名和验签工作
     * 签名验证器：封装了所有下载平台证书的参数；获得平台证书也就获得了微信平台的公钥 ，可以进行 来自微信平台消息的验签工作
     * 平台证书：平台证书封装了微信的公钥，商户可以使用平台证书中的公钥进行验签。
     * @return
     * @throws NotFoundException
     * @throws HttpCodeException
     * @throws GeneralSecurityException
     * @throws IOException
     *
     */

    @Bean(name = "verifier")
    public Verifier getVerifier() throws NotFoundException, HttpCodeException, GeneralSecurityException, IOException {
        log.info("获取验证器");
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();

        //创建私钥签名对象
        PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, getPrivateKey());
        //创建
        WechatPay2Credentials wechatPay2Credentials =  new WechatPay2Credentials(mchId, privateKeySigner);
// 向证书管理器增加需要自动更新平台证书的商户信息（商户id，商户序列号：平台为商户找到对应的证书；apiV3Key对称加密密钥 ）
        certificatesManager.putMerchant(mchId,wechatPay2Credentials, apiV3Key.getBytes(StandardCharsets.UTF_8));
// ... 若有多个商户号，可继续调用putMerchant添加商户信息

// 从证书管理器中获取verifier
        Verifier verifier = certificatesManager.getVerifier(mchId);


        log.info("返回验证器");
        return verifier;

    }



    /**
     * 获取http请求对象
     * @param verifier
     * @return
     */

    @Bean(name = "client")
    public HttpClient getHttpClient(@Qualifier("verifier") Verifier verifier) {
        log.info("获取HttpClient");

        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, getPrivateKey())
                .withValidator(new WechatPay2Validator(verifier));
        // 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient

        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();
        return httpClient;

    }

}
